home *** CD-ROM | disk | FTP | other *** search
/ Programming an RTS Game with Direct3D / Programming an RTS Game with Direct3D.iso / Examples / Chapter 5 / Example 5.6 / camera.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2006-07-17  |  6.2 KB  |  241 lines

  1. #include "camera.h"
  2.  
  3. CAMERA::CAMERA()
  4. {
  5.     Init(NULL);
  6. }
  7.  
  8. void CAMERA::Init(IDirect3DDevice9* Dev)
  9. {
  10.     m_pDevice = Dev;
  11.     m_alpha = m_beta = 0.5f;
  12.     m_radius = 10.0f;
  13.     m_fov = D3DX_PI / 4.0f;
  14.  
  15.     m_eye = D3DXVECTOR3(50.0f, 50.0f, 50.0f);
  16.     m_focus = D3DXVECTOR3(0.0f, 0.0f, 0.0f);
  17. }
  18.  
  19. void CAMERA::Scroll(D3DXVECTOR3 vec)
  20. {
  21.     D3DXVECTOR3 newFocus = m_focus + vec;
  22.    m_focus = newFocus;
  23. }
  24.  
  25. void CAMERA::Pitch(float f)
  26. {
  27.     m_beta += f;
  28.  
  29.     if(m_beta > (D3DX_PI / 2.0f) - 0.05f)m_beta = D3DX_PI / 2.0f - 0.05f;
  30.     if(m_beta < 0.3f)m_beta = 0.3f;
  31. }
  32.  
  33. void CAMERA::Yaw(float f)
  34. {
  35.     m_alpha += f;
  36.     if(m_alpha > D3DX_PI * 2.0f)m_alpha -= D3DX_PI * 2.0f;
  37.     if(m_alpha < -D3DX_PI * 2.0f)m_alpha += D3DX_PI * 2.0f;
  38. }
  39.  
  40. void CAMERA::Zoom(float f)
  41. {
  42.     m_fov += f;
  43.  
  44.     if(m_fov < 0.1f)m_fov = 0.1f;
  45.     if(m_fov > D3DX_PI / 2.0f)m_fov = D3DX_PI / 2.0f;
  46. }
  47.  
  48. void CAMERA::ChangeRadius(float f)
  49. {
  50.     m_radius += f;
  51.  
  52.     if(m_radius < 5.0f)m_radius = 5.0f;
  53.     if(m_radius > 100.0f)m_radius = 100.0f;
  54. }
  55.  
  56. void CAMERA::Update(MOUSE &mouse, float timeDelta)
  57. {
  58.     //Restrict focus movment to the xz-plane
  59.     m_right.y = m_look.y = 0.0f;
  60.     D3DXVec3Normalize(&m_look, &m_look);
  61.     D3DXVec3Normalize(&m_right, &m_right);
  62.  
  63.     //Move Focus (i.e. Scroll)
  64.     if(mouse.x < mouse.m_viewport.left + 10)    Scroll(-m_right * timeDelta * 30.0f);
  65.     if(mouse.x > mouse.m_viewport.right - 10)    Scroll(m_right * timeDelta * 30.0f);
  66.     if(mouse.y < mouse.m_viewport.top + 10)        Scroll(m_look * timeDelta * 30.0f);
  67.     if(mouse.y > mouse.m_viewport.bottom - 10)    Scroll(-m_look * timeDelta * 30.0f);
  68.  
  69.     //Move Camera (i.e. Change Angle)
  70.     if(KEYDOWN(VK_LEFT))Yaw(-timeDelta);
  71.     if(KEYDOWN(VK_RIGHT))Yaw(timeDelta);
  72.     if(KEYDOWN(VK_UP))Pitch(timeDelta);
  73.     if(KEYDOWN(VK_DOWN))Pitch(-timeDelta);
  74.     
  75.     //Zoom (i.e. change fov)
  76.     if(KEYDOWN(VK_ADD))Zoom(-timeDelta);
  77.     if(KEYDOWN(VK_SUBTRACT))Zoom(timeDelta);
  78.  
  79.     //Change m_radius
  80.     if(mouse.WheelUp())  ChangeRadius(-1.0f);
  81.     if(mouse.WheelDown())ChangeRadius(1.0f);
  82.  
  83.     //Calculate Eye Position
  84.     float sideRadius = m_radius * cos(m_beta);
  85.     float height = m_radius * sin(m_beta);
  86.  
  87.     m_eye = D3DXVECTOR3(m_focus.x + sideRadius * cos(m_alpha),
  88.                       m_focus.y + height, 
  89.                       m_focus.z + sideRadius * sin(m_alpha));
  90.  
  91.     if(m_pDevice != NULL)
  92.     {
  93.         D3DXMATRIX view = GetViewMatrix();
  94.         D3DXMATRIX projection = GetProjectionMatrix();
  95.  
  96.         m_pDevice->SetTransform(D3DTS_VIEW, &view);
  97.         m_pDevice->SetTransform(D3DTS_PROJECTION, &projection);
  98.  
  99.         CalculateFrustum(view, projection);
  100.     }    
  101. }
  102.  
  103. D3DXMATRIX CAMERA::GetViewMatrix()
  104. {
  105.     D3DXMATRIX  matView;
  106.     D3DXMatrixLookAtLH(&matView, &m_eye, &m_focus, &D3DXVECTOR3(0.0f, 1.0f, 0.0f));
  107.  
  108.     m_right.x = matView(0,0);
  109.     m_right.y = matView(1,0);
  110.     m_right.z = matView(2,0);
  111.     D3DXVec3Normalize(&m_right, &m_right);
  112.  
  113.     m_look.x = matView(0,2);
  114.     m_look.y = matView(1,2);
  115.     m_look.z = matView(2,2);
  116.     D3DXVec3Normalize(&m_look, &m_look);
  117.  
  118.     return  matView;
  119. }
  120.  
  121. D3DXMATRIX CAMERA::GetProjectionMatrix()
  122. {
  123.     D3DXMATRIX  matProj;
  124.     float aspect = 800.0f / 600.0f;
  125.     D3DXMatrixPerspectiveFovLH(&matProj, m_fov, aspect, 1.0f, 1000.0f );
  126.     return matProj;
  127. }
  128.  
  129. void CAMERA::CalculateFrustum(D3DXMATRIX view, D3DXMATRIX projection)
  130. {
  131.     try
  132.     {
  133.         // Get combined matrix
  134.         D3DXMATRIX matComb;
  135.         D3DXMatrixMultiply(&matComb, &view, &projection);
  136.  
  137.         // Left clipping plane
  138.         m_frustum[0].a = matComb._14 + matComb._11; 
  139.         m_frustum[0].b = matComb._24 + matComb._21; 
  140.         m_frustum[0].c = matComb._34 + matComb._31; 
  141.         m_frustum[0].d = matComb._44 + matComb._41;
  142.  
  143.         // Right clipping plane 
  144.         m_frustum[1].a = matComb._14 - matComb._11; 
  145.         m_frustum[1].b = matComb._24 - matComb._21; 
  146.         m_frustum[1].c = matComb._34 - matComb._31; 
  147.         m_frustum[1].d = matComb._44 - matComb._41;
  148.  
  149.         // Top clipping plane 
  150.         m_frustum[2].a = matComb._14 - matComb._12; 
  151.         m_frustum[2].b = matComb._24 - matComb._22; 
  152.         m_frustum[2].c = matComb._34 - matComb._32; 
  153.         m_frustum[2].d = matComb._44 - matComb._42;
  154.  
  155.         // Bottom clipping plane 
  156.         m_frustum[3].a = matComb._14 + matComb._12; 
  157.         m_frustum[3].b = matComb._24 + matComb._22; 
  158.         m_frustum[3].c = matComb._34 + matComb._32; 
  159.         m_frustum[3].d = matComb._44 + matComb._42;
  160.  
  161.         // Near clipping plane 
  162.         m_frustum[4].a = matComb._13; 
  163.         m_frustum[4].b = matComb._23; 
  164.         m_frustum[4].c = matComb._33; 
  165.         m_frustum[4].d = matComb._43;
  166.  
  167.         // Far clipping plane 
  168.         m_frustum[5].a = matComb._14 - matComb._13; 
  169.         m_frustum[5].b = matComb._24 - matComb._23; 
  170.         m_frustum[5].c = matComb._34 - matComb._33; 
  171.         m_frustum[5].d = matComb._44 - matComb._43; 
  172.  
  173.         //Normalize planes
  174.         for(int i=0;i<6;i++)
  175.             D3DXPlaneNormalize(&m_frustum[i], &m_frustum[i]);
  176.     }
  177.     catch(...)
  178.     {
  179.         debug.Print("Error in CAMERA::CalculateFrustum()");
  180.     }
  181. }
  182.  
  183. bool CAMERA::Cull(BBOX bBox)
  184. {
  185.     try
  186.     {
  187.         //For each plane in the view frustum
  188.         for(int f=0;f<6;f++)
  189.         {
  190.             D3DXVECTOR3 c1, c2;
  191.  
  192.             //Find furthest point (n1) & nearest point (n2) to the plane
  193.             if(m_frustum[f].a > 0.0f)    {c1.x = bBox.max.x; c2.x = bBox.min.x;}
  194.             else                    {c1.x = bBox.min.x; c2.x = bBox.max.x;}
  195.             if(m_frustum[f].b > 0.0f)    {c1.y = bBox.max.y; c2.y = bBox.min.y;}
  196.             else                    {c1.y = bBox.min.y; c2.y = bBox.max.y;}
  197.             if(m_frustum[f].c > 0.0f)    {c1.z = bBox.max.z; c2.z = bBox.min.z;}
  198.             else                    {c1.z = bBox.min.z; c2.z = bBox.max.z;}
  199.  
  200.             float distance1 = m_frustum[f].a * c1.x + m_frustum[f].b * c1.y + 
  201.                               m_frustum[f].c * c1.z + m_frustum[f].d;
  202.             float distance2 = m_frustum[f].a * c2.x + m_frustum[f].b * c2.y + 
  203.                               m_frustum[f].c * c2.z + m_frustum[f].d;
  204.  
  205.             //If both points are on the negative side of the plane, Cull!
  206.             if(distance1 < 0.0f && distance2 < 0.0f)
  207.                 return true;
  208.         }
  209.  
  210.         //Object is inside the volume
  211.         return false;
  212.     }
  213.     catch(...)
  214.     {
  215.         debug.Print("Error in CAMERA::Cull()");
  216.         return true;
  217.     }
  218. }
  219.  
  220. bool CAMERA::Cull(BSPHERE bSphere)
  221. {
  222.     try
  223.     {
  224.         //For each plane in the view frustum
  225.         for(int f=0;f<6;f++)
  226.         {
  227.             float distance = D3DXVec3Dot(&bSphere.center, &D3DXVECTOR3(m_frustum[f].a, m_frustum[f].b, m_frustum[f].c)) + m_frustum[f].d;
  228.  
  229.             if(distance < -bSphere.radius)
  230.                 return true;
  231.         }
  232.  
  233.         //Object is inside the volume
  234.         return false;
  235.     }
  236.     catch(...)
  237.     {
  238.         debug.Print("Error in CAMERA::Cull()");
  239.         return true;
  240.     }
  241. }